package com.xiaojie.learn.util;

public abstract class AbstractShortURLUtil {

    private static final String SHORT_URL_KEY = "short_url_key";
    private static final String LOCALHOST = "http://localhost:9999/";
    private static final String SHORT_LONG_PREFIX = "short_long_prefix:";
    private static final String CACHE_KEY_PREFIX = "cache_key_prefix:";
    private static final int CACHE_SECONDS = 1 * 60 * 60;

    public String getShortURL(String longURL,Decimal decimal){
        //查询缓存
        String cache = checkCache(CACHE_KEY_PREFIX + longURL);
        if(cache != null){
            return LOCALHOST  + toOtherBaseString(Long.valueOf(cache),decimal.x);
        }
        //自增
        long num = getShortNum(SHORT_URL_KEY);
        //持久化短-长URL的映射关系
        persist(SHORT_LONG_PREFIX + num,longURL);
        //写入缓存
        pushCache(CACHE_KEY_PREFIX + longURL,CACHE_SECONDS,String.valueOf(num));

        return LOCALHOST  + toOtherBaseString(num,decimal.x);
    }

    public String getLongURL(String shortURL){
        if(shortURL == null || shortURL.equals("") || !shortURL.startsWith(LOCALHOST)){
            return "";
        }
        String num = shortURL.replace(LOCALHOST,"");
        return getLong(SHORT_LONG_PREFIX + num);
    }

    abstract String checkCache(String cachekey);
    abstract void pushCache(String cachekey,int time,String value);
    abstract long getShortNum(String SHORT_URL_KEY);
    abstract void persist(String shortKey,String longURL);
    abstract String getLong(String shortURL);

    //由10进制的数字转换到其他进制
    private String toOtherBaseString(long n,int base){
        long num = 0;
        if(n < 0){
            num = ((long) 2 * 0x7fffffff) + n + 2;
        }else{
            num = n;
        }
        char[] buf = new char[32];
        int charPos = 32;
        while ((num/base)>0){
            buf[--charPos] = digits[(int)(num % base)];
            num /= base;
        }
        buf[--charPos] = digits[(int)(num % base)];
        return new String(buf,charPos,(32-charPos));
    }


    enum Decimal {
        D32(32),
        D64(64);

        int x;

        Decimal(int x) {
            this.x = x;
        }
    }

    //字符集合
    final static char[] digits = {
            '0','1','2','3','4','5','6','7','8','9'
            ,'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
            ,'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
    };


}
